﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Graphviz4Net.Graphs;
using System.ComponentModel;
using System.IO;
using System.Web.Script.Serialization;
using Graphviz4Net.WPF.Example;

namespace LogAnalyzer
{   
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public int current = 0;
        public List<LogMessage> Log { get; set; }
        private List<string> activeRouting;

        public MainWindowViewModel()
        {
            var graph = new Graph<GraphComponent>();
            activeRouting = new List<string>();
            LoadLog();
         
            this.Graph = graph;
            this.Graph.Changed += GraphChanged;
            this.NewPersonName = "Enter new name";
        }

        public Graph<GraphComponent> Graph { get; private set; }

        public string NewPersonName { get; set; }

        public IEnumerable<string> PersonNames
        {
            get { return this.Graph.AllVertices.Select(x => x.Id); }
        }

        public string NewEdgeStart { get; set; }

        public string NewEdgeEnd { get; set; }

        public string NewEdgeLabel { get; set; }

        public void CreateEdge()
        {
            if (string.IsNullOrWhiteSpace(this.NewEdgeStart) ||
                string.IsNullOrWhiteSpace(this.NewEdgeEnd))
            {
                return;
            }

            this.Graph.AddEdge(
                new Edge<GraphComponent>
                    (this.GetPerson(this.NewEdgeStart), 
                    this.GetPerson(this.NewEdgeEnd))
                    {
                        Label = this.NewEdgeLabel
                    });
        }

        public void CreatePerson()
        {
            if (this.PersonNames.Any(x => x == this.NewPersonName))
            {
                // such a person already exists: there should be some validation message, but 
                // it is not so important in a demo
                return;
            }

            var p = new Node() { address = this.NewPersonName };
            this.Graph.AddVertex(p);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void GraphChanged(object sender, GraphChangedArgs e)
        {
            this.RaisePropertyChanged("PersonNames");
        }

        private void RaisePropertyChanged(string property)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        private Node GetPerson(string name)
        {
            return null; //this.Graph.AllVertices.First(x => string.CompareOrdinal(x.Id, name) == 0);
        }

        private void LoadLog()
        {
            DirectoryInfo di = new DirectoryInfo(@"C:\Users\Sergio\Desktop\log");
            Log = new List<LogMessage>();
            foreach (var fi in di.GetFiles())
            {
                var stream = fi.OpenText();
                while (!stream.EndOfStream)
                {
                    var json = stream.ReadLine();
                    var logEntry = new JavaScriptSerializer().Deserialize<LogMessage>(json);
                    Log.Add(logEntry);
                }
            }

            //Log = Log.OrderBy(x => x.time).ToList();
        }

        public void Next()
        {
            var msg = Log[current];
            if (msg.what.type.Equals("Start"))
            {
                //if (Log[current].to.Equals("akka://System/user/1"))
                //{
                msg.to.showLeaf += to_showLeaf;
                this.Graph.AddVertex(msg.to);
                //}
            }
            else if (msg.what.type.Equals("Join"))
            {
                if (activeRouting.Contains(msg.what.content.id))
                {
                    var from = this.Graph.Vertices.First(x => x.Id.Equals(msg.from));
                    var to = this.Graph.Vertices.First(x => x.Equals(msg.to));
                    this.Graph.AddEdge(new Edge<GraphComponent>(from, to, new Arrow()));
                }
                else
                {
                    activeRouting.Add(msg.what.content.id);
                    //var from = new VertexControl();
                    //from.Vertex = msg.from;
                    //this.graph.AddVertex(from);

                    var from = this.Graph.Vertices.First(x => x.Id.Equals(msg.from));
                    var to = this.Graph.Vertices.First(x => x.Equals(msg.to));

                    ((Node)to).leaf = msg.what.state.leaf;

                    this.Graph.AddEdge(new Edge<GraphComponent>(from, to, new Arrow()) { Label = "Join", Color = "Gold" });
                }
            }
            else if (msg.what.type.Equals("JoinResponse"))
            {
                var from = this.Graph.Vertices.First(x => x.Id.Equals(msg.from));
                var to = this.Graph.Vertices.First(x => x.Equals(msg.to));

                ((Node)to).leaf = msg.what.state.leaf;

                this.Graph.AddEdge(new Edge<GraphComponent>(from, to, new Arrow()) { Label = "JoinResponse", Color = "Blue" });


            }
            else if (msg.what.type.Equals("JoinDone"))
            {
                var from = this.Graph.Vertices.First(x => x.Id.Equals(msg.from));
                var to = this.Graph.Vertices.First(x => x.Equals(msg.to));

                ((Node)to).leaf = msg.what.state.leaf;

                var edge = new Edge<GraphComponent>(from, to, new Arrow()) { Label = "JoinDone", Color = "Red" };

                this.Graph.AddEdge(edge);
            }

            current++;

            if (current > 20)
            {
                foreach (var e in this.Graph.Edges)
                {
                    ((Edge<GraphComponent>)e).Color = "Black";
                }
            }
        }

        void to_showLeaf(object sender, EventArgs e)
        {
            
        }
    }
}
